/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 dialog_campaign_score.cpp

	$Header: /resource_editor/dialog_campaign_score.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )


#include "dialog_campaign_score.h"

#include "adventure_map.h"
#include "bitmap_group_cache.h"
#include "bound_handler.h"
#include "button_cache.h"
#include "carryover_data.h"
#include "score_computer.h"
#include "dialog_high_score.h"
#include "external_string.h"
#include "format_string.h"
#include "high_scores.h"
#include "interface_help.h"
#include "item_help_block.h"
#include "main_menu.h"
#include "map_header.h"
#include "scrollbar.h"
#include "simple_dialog.h"
#include "standard_fonts.h"


extern t_button_cache g_ok_button;
static t_bitmap_group_cache g_layout( "dialog.campaign_score" );


static t_external_string const k_campaign_score_title( "title.campaign_score" );
static t_external_string const k_text_high_score_save_problem( "high_score_save_problem.misc" );
static t_external_string const k_text_average_score("average.campaign_score");


// ------------------------------------------------------------------
// Present the final score for a campaign and its constituent maps
// ------------------------------------------------------------------
t_dialog_campaign_score::t_dialog_campaign_score( t_adventure_map* last_map, std::string const & player_name, t_window* parent )
	: t_bitmap_layer_window( 0, t_screen_point(0,0), parent )
{
	t_screen_rect rect;

	// Gather our underlying data
	m_player_name = player_name;
	gather_data( last_map );	

	// load bitmaps
	m_layout = g_layout.get();

	// set background
	t_bitmap_layer const* layer = m_layout->find( "background" );
	set_bitmap( layer );

 	// center ourselves on our parent window
	rect = layer->get_rect();
	rect += t_screen_point( (get_parent()->get_width()  - rect.width())  / 2, 
		                    (get_parent()->get_height() - rect.height()) / 2 );
	move( rect );
	set_drop_shadow();

	// create_buttons and title
	create_title();
	create_buttons();

	// create scrollbar if necessary
	int excess_maps = m_data.size() - m_line_items.size();
	if (excess_maps > 0)
	{
		rect = m_layout->find( "scrollbar" )->get_rect();
		m_scrollbar = new t_scrollbar( rect.top_left(), rect.height(), this, 0, excess_maps );
		m_scrollbar->set_handler( bound_handler( *this, &t_dialog_campaign_score::scroll ));
	}
	else
	{
		m_scrollbar = NULL;
	}

	// Force an initial refresh
	scroll( NULL, 0 );
}


// ------------------------------------------------------------------
// Gather the map names and scores plus the overall campaign name
// ------------------------------------------------------------------
void t_dialog_campaign_score::gather_data( t_adventure_map const * last_map )
{
	assert( last_map->is_multi_scenario() );

	// First get the campaign file header
	t_campaign_file_ref const & file_ref = last_map->get_file_ref();
	t_multi_scenario_campaign_file_header_ptr file_header_ptr = create_multi_scenario_campaign_file_header( file_ref, 0 );
	if ( file_header_ptr.get() == 0 )
	{
		file_open_failure( file_ref );
		return;
	}

	// Get the campaign name
	m_campaign_name = file_header_ptr->get_name();

	// Get the map's carry out data (which has the score list in it)
	t_carryover_data const * carry_out_data = last_map->get_carry_out_data();
	assert( carry_out_data );
	assert( carry_out_data->get_scenario_score_count() == file_header_ptr->get_map_count() );

	// Get each map name and store its name and score
	m_campaign_days		= 0;
	m_campaign_score	= 0;

  int map_number = 0;
	for (map_number = 0; map_number < file_header_ptr->get_map_count(); map_number++ )
	{
		t_line_data data;

		t_map_header const & header = file_header_ptr->get_map_header( map_number );
		data.map_name		= header.name;

		t_scenario_score score = carry_out_data->get_scenario_score( map_number );
		data.score_string	= format_string( "%0d", score.m_score );

		m_campaign_days += score.m_days;
		m_campaign_score += score.m_score;

		m_data.push_back( data );
	}
	m_score_average = m_campaign_score / map_number;
	m_campaign_score = m_score_average * k_campaign_score_multiplier;
	m_campaign_creature_index = get_rank_creature( m_campaign_score, k_creature_score_range*k_campaign_score_multiplier );
}


// ------------------------------------------------------------------
// Just place the title string at the top
// ------------------------------------------------------------------
void t_dialog_campaign_score::create_title()
{
	t_text_window* text_window;
	t_screen_rect  rect = m_layout->find("title")->get_rect();
	text_window = new t_text_window( get_font( rect.height() ), rect, this, k_campaign_score_title, t_pixel_24(0,0,0));
	text_window->set_center_horizontal();
	text_window->set_drop_shadow( true, t_pixel_24(200,200,200));
}

// ------------------------------------------------------------------
// ------------------------------------------------------------------
void t_dialog_campaign_score::create_buttons()
{
	// create the close button
	t_help_block const&     shared_help = get_help_block( "shared" );
	t_screen_point point = m_layout->find( "close_button" )->get_rect().top_left();
	m_ok_button = new t_button( g_ok_button.get(), point, this );
	m_ok_button->set_click_handler( bound_handler( *this, &t_dialog_campaign_score::close_click ));
  set_help( m_ok_button, shared_help, "ok" );


	// Collect the common elements
	t_bitmap_layer const* frame_layer = m_layout->find( "map_background" );
	const t_screen_rect frame_rect		= frame_layer->get_rect();
	const t_screen_point frame_offset	= frame_rect.top_left();
	const t_screen_rect name_rect		= m_layout->find( "map_name" )->get_rect() - frame_offset;
	const t_screen_rect score_rect		= m_layout->find( "map_score" )->get_rect() - frame_offset;

	const t_pixel_24	text_color( 0, 0, 0 );
	const t_pixel_24	shadow_color( 200,200,200 );


	// Create the overall campaign score box
	t_bitmap_layer_window	* frame	= NULL;
	t_text_window			* text_window = NULL;

	// create frame for average score
	t_screen_point location = m_layout->find( "map_average" )->get_rect().top_left();

	frame = new t_bitmap_layer_window( frame_layer, location - frame_offset, this );
	text_window = new t_text_window( get_font( name_rect.height() ), name_rect, frame,
									 k_text_average_score, text_color );
	text_window = new t_text_window( get_font( score_rect.height() ), score_rect, frame,
									 format_string( "%i", m_score_average ), text_color );
	text_window->set_right_justified();

	// create multiplier
	location = m_layout->find( "multiplier" )->get_rect().top_left();
	frame = new t_bitmap_layer_window( frame_layer, location - frame_offset, this );
	text_window = new t_text_window( get_font( score_rect.height() ), score_rect, frame,
									 "x5", text_color );
	text_window->set_right_justified();
	
	// Create the frame for this item
	t_screen_point campaign_location = m_layout->find( "Campaign" )->get_rect().top_left();
	frame = new t_bitmap_layer_window( frame_layer, campaign_location - frame_offset, this );
	
	// Put in the text box for the name
	text_window = new t_text_window( get_font( name_rect.height() ), name_rect, frame, 
									 m_campaign_name, text_color );
	
	// Put in the text box for the score
	std::string score_string = format_string( "%0d", m_campaign_score );

	text_window = new t_text_window( get_font( score_rect.height() ), score_rect, frame, 
									 score_string, text_color );
	text_window->set_justification( k_justify_right );


	// Now create a button and some children for each line of the display
	for (int i = 0; i < m_layout->size(); i++)
	{
		// See if this is a position marker for a line item (based on its name)
		t_bitmap_layer const* layer = &(*m_layout)[i];
		if (strnicmp( layer->get_name().c_str(), "line_", 5 ) != 0)
			continue;

		// find the location of this button
		t_screen_point	button_location	= layer->get_rect().top_left();

		// Create a new line item
		t_line_display	line_item;

		// Create the frame for this item
		line_item.frame	= new t_bitmap_layer_window( frame_layer, button_location - frame_offset, this );

		// Put in the text box for the map name
		line_item.map_name	= new t_text_window( get_font( name_rect.height() ), name_rect, 
												 line_item.frame, "", text_color );

		// Put in the text box for the map score
		line_item.score_display	= new t_text_window( get_font( score_rect.height() ), score_rect, 
													 line_item.frame, "", text_color );
		line_item.score_display->set_justification( k_justify_right );

		m_line_items.push_back( line_item );
	}
}


// ------------------------------------------------------------------
// ------------------------------------------------------------------
void t_dialog_campaign_score::scroll( t_scrollbar* scrollbar, int top_line )
{
	int line;
	int index;

	m_top_line = top_line;

	// set line items according to header data.
	line = 0;
	for (index = top_line; index < m_data.size() && line < m_line_items.size(); index++, line++)
	{
		m_line_items[line].map_name->set_text( m_data[index].map_name );
		m_line_items[line].score_display->set_text( m_data[index].score_string );
		m_line_items[line].frame->set_visible( true );
	}
	// hide extra line items
	while (line < m_line_items.size())
	{
		m_line_items[line].frame->set_visible( false );
		line++;
	}
}


// ------------------------------------------------------------------
// Handle the close click -- we update the hall of fame here.
// ------------------------------------------------------------------
void t_dialog_campaign_score::close_click( t_button* )
{
	bool				new_high_score	= false;
	t_high_scores_ptr	scores_ptr		= read_high_scores_file();

	// check high scores
	if ( scores_ptr->check_high_scores( m_campaign_name, m_campaign_days, m_campaign_score, m_player_name, false, m_campaign_creature_index ) )
	{
		new_high_score = true;
	}

	// Close ourselves
	t_window_ptr parent = get_parent();
	close();	// close all child windows too

	// If the high scores just changed, show the dialog
	if( new_high_score )
	{
		// write out the new scores to disk
		if (!write_high_scores_file( scores_ptr ))
		{
			ok_dialog( k_text_high_score_save_problem, true );
		}

		// Present the results
		t_counted_ptr<t_high_score_dialog> dialog;
		dialog = new t_high_score_dialog( parent, *scores_ptr, false );
		dialog->run_modal();
	}
}


